package web

import (
	"commerce/cache"
	"commerce/common"
	"commerce/data"
	"commerce/model"
	"commerce/utils"
	"commerce/vo"
	"encoding/json"
	"net/http"
	"strconv"
	"time"
)

/* 此文件是 分类 请求 */

func CatalogIndex(w http.ResponseWriter, r *http.Request) {

	var res vo.CatalogIndexVo

	// 先从缓存取
	catalogListCache, err := cache.Get(common.CatalogJSON)

	// 缓存中有，直接使用缓存数据
	if err == nil && len(catalogListCache) > 0 {

		json.Unmarshal([]byte(catalogListCache), &res)

		j, _ := json.Marshal(vo.Ok(res))
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(j)
		return
	}
	// 缓存中没有，获取分布式锁，查询mysql, 放入缓存，释放锁
	res = getJsonCatalogWithRedisLock()

	j, _ := json.Marshal(vo.Ok(res))
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(j)
}

func getJsonCatalogWithRedisLock() vo.CatalogIndexVo {

	uuid := utils.Uuid()
	locked := cache.SetIfAbsent(common.CatalogJSONLock, uuid, 10)

	if locked {
		indexVo := queryCatalogDataAndAddToCache()
		// 释放锁
		_, err := cache.ReleaseLock(common.CatalogJSONLock, uuid, common.ReleaseLockLuaScript)
		common.Info.Println("release redis lock: ", common.CatalogJSONLock, uuid, err)

		return indexVo
	} else {
		time.Sleep(500 * time.Millisecond)
		// 重试
		return getJsonCatalogWithRedisLock()
	}
}

func queryCatalogDataAndAddToCache() vo.CatalogIndexVo {

	var res vo.CatalogIndexVo

	catalogListCache, err := cache.Get(common.CatalogJSON)
	// 再次查缓存数据(说不定，这获取锁的功夫，好不容易进来后，发现别人已经把数据存入缓存了！)
	if err == nil && len(catalogListCache) > 0 {
		json.Unmarshal([]byte(catalogListCache), &res)
		return res
	}
	categories, err := data.ListAllCategoryForApp()
	// 查询db出错，这似乎没法玩了，先直接返回吧……
	if err != nil {
		return res
	}
	var catList []vo.CategoryVo
	//var flag = true

	for _, c := range categories {
		// 顶级分类
		if c.Parent == 0 {
			var cat vo.CategoryVo
			cat.Id = c.Id
			cat.Name = c.Name
			cat.SubCategoryList = getSubLevelCategory(c.Id, categories)
			//if flag {
			cat.WapBannerUrl = c.MainImg
			cat.FrontName = c.Description
			//}
			//flag = false

			catList = append(catList, cat)
		}
	}
	res.CategoryList = catList
	res.CurrentCategory = catList[0]

	// 放入缓存
	data, _ := json.Marshal(res)
	cache.SetWithTTL(common.CatalogJSON, string(data), common.CatalogJSONTTL)

	return res
}

func getSubLevelCategory(parentCatId int, all []model.Category) []vo.CategoryVo {

	var list []vo.CategoryVo

	for _, c := range all {
		if parentCatId == c.Parent {
			list = append(list, vo.CategoryVo{Id: c.Id, Name: c.Name, WapBannerUrl: c.MainImg, FrontName: c.Description})
		}
	}
	return list
}

func SearchIndex(w http.ResponseWriter, r *http.Request) {

	var res vo.SearchIndexVo
	var hkList []vo.Hk
	hwList, err := cache.ZRange(common.HOT_KW_LIST, 0, -1)
	if err != nil || len(hwList) == 0 {
		// 从db中查询
		hwList, err = data.ListGoodsNameByPriority(common.HOT_KW_LIMIT)
		if err != nil {
			common.Error.Println("SearchIndex err:", err)
			hwList = make([]string, 0)
		}
	}
	for _, h := range hwList {
		hkList = append(hkList, vo.Hk{IsHot: 1, Keyword: h})
	}
	res.HotKeyword = hkList
	res.DefaultKeyword = "ncepu"

	j, _ := json.Marshal(vo.Ok(res))
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(j)
}

// @todo 打算用riot搜索，把商品名称维护到里面，然后搜索出来相关的商品名称，返回给app

func SearchHelper(w http.ResponseWriter, r *http.Request) {

	j, _ := json.Marshal(vo.Ok(data.ListSkuNameByKeyword(r.PostFormValue("keyword"))))
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(j)
}

func CurrentCategory(w http.ResponseWriter, r *http.Request) {

	categoryId, _ := strconv.Atoi(r.PostFormValue("id"))

	categories, err := data.ListCategoryById(categoryId)

	//category, err := data.GetCategoryById(categoryId)
	if err != nil {
		common.Error.Printf("CurrentCategory err:%v", err)
		j, _ := json.Marshal(vo.Err(err.Error()))
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(j)
		return
	}
	var res vo.CategoryVo

	res.Id = categoryId

	for _, c := range categories {
		if categoryId == c.Id {
			res.Name = c.Name
			res.WapBannerUrl = c.MainImg
			res.FrontName = c.Description
			break
		}
	}
	res.SubCategoryList = getSubLevelCategory(categoryId, categories)

	j, _ := json.Marshal(vo.Ok(res))
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(j)
}
